package org.mutabilitydetector;
/*
* #%L
* MutabilityDetector
* %%
* Copyright (C) 2008 - 2014 Graham Allan
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mutabilitydetector.MutabilityReason.ABSTRACT_TYPE_TO_FIELD;
import static org.mutabilitydetector.TestUtil.formatReasons;
import static org.mutabilitydetector.TestUtil.getAnalysisResult;
import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable;
import static org.mutabilitydetector.unittesting.MutabilityAssert.assertInstancesOf;
import static org.mutabilitydetector.unittesting.MutabilityMatchers.areEffectivelyImmutable;
import static org.mutabilitydetector.unittesting.MutabilityMatchers.areNotImmutable;
import java.util.Collection;
import org.hamcrest.CoreMatchers;
import org.junit.Rule;
import org.junit.Test;
import org.mutabilitydetector.benchmarks.ImmutableExample;
import org.mutabilitydetector.benchmarks.MutableByHavingPublicNonFinalField;
import org.mutabilitydetector.benchmarks.MutableByNoCopyOfIndirectlyConstructedField;
import org.mutabilitydetector.benchmarks.escapedthis.PassesThisReferenceToMethodCall;
import org.mutabilitydetector.benchmarks.mutabletofield.CollectionFields.CopyListIntoNewArrayListAndUnmodifiableListIdiom;
import org.mutabilitydetector.benchmarks.mutabletofield.CollectionFields.StaticMethodDoesTheCopying;
import org.mutabilitydetector.benchmarks.mutabletofield.MutableByAssigningAbstractTypeToField;
import org.mutabilitydetector.benchmarks.mutabletofield.MutableByHavingMutableFieldAssigned;
import org.mutabilitydetector.benchmarks.mutabletofield.UnsafelyCopedCollectionFieldWithAllowedGenericType;
import org.mutabilitydetector.benchmarks.sealed.MutableByNotBeingFinalClass;
import org.mutabilitydetector.benchmarks.settermethod.MutableByHavingSetterMethod;
import org.mutabilitydetector.benchmarks.types.EnumType;
import org.mutabilitydetector.benchmarks.visibility.EffectivelyImmutable;
import org.mutabilitydetector.benchmarks.visibility.SafelyPublishesUsingVolatile;
import org.mutabilitydetector.junit.FalsePositive;
import org.mutabilitydetector.junit.IncorrectAnalysisRule;
public class MutabilityCheckerTest {
@Rule public IncorrectAnalysisRule rule = new IncorrectAnalysisRule();
@Test
public void immutableExample() throws Exception {
assertImmutable(ImmutableExample.class);
}
@Test
public void effectivelyImmutableByHavingNonFinalField() throws Exception {
assertInstancesOf(EffectivelyImmutable.class, areEffectivelyImmutable());
}
@Test
@FalsePositive("Ensures non-final fields are immediately visible")
public void volatileAssignmentOfFieldEnsuresOtherNonFinalFieldsAreImmediatelyVisible() throws Exception {
assertImmutable(SafelyPublishesUsingVolatile.class);
}
@Test
public void mutableByAllowingAccessToNonFinalField() throws Exception {
assertInstancesOf(MutableByHavingPublicNonFinalField.class, areNotImmutable());
}
@Test
public void mutableByHavingMutableFieldAssigned() throws Exception {
assertInstancesOf(MutableByHavingMutableFieldAssigned.class, areNotImmutable());
}
@Test
public void mutableByHavingSetterMethod() throws Exception {
assertInstancesOf(MutableByHavingSetterMethod.class, areNotImmutable());
}
@Test
public void mutableByNoCopyOfIndirectlyConstructedField() throws Exception {
assertInstancesOf(MutableByNoCopyOfIndirectlyConstructedField.class, areNotImmutable());
}
@Test
public void immutableByCopyingMutableListIntoNewArrayListAndUnmodifiableList() throws Exception {
assertImmutable(CopyListIntoNewArrayListAndUnmodifiableListIdiom.class);
}
@FalsePositive("Doesn't copy collection in constructor.")
@Test
public void immutableByCopyingMutableListIntoNewArrayListAndUnmodifiableListInStaticMethod() throws Exception {
assertImmutable(StaticMethodDoesTheCopying.class);
}
@Test
public void mutableByNotBeingFinalClass() throws Exception {
assertInstancesOf(MutableByNotBeingFinalClass.class, areNotImmutable());
}
@Test
public void mutableByLettingTheThisReferenceEscapeDuringConstruction() throws Exception {
assertInstancesOf(PassesThisReferenceToMethodCall.AsOneOfSeveralParameters.class, areNotImmutable());
}
@Test
public void enumTypesAreImmutable() throws Exception {
assertImmutable(EnumType.class);
}
@Test
public void unsafelyCopiedCollectionsAreStillMutableEvenIfElementTypeIsAllowed() throws Exception {
assertInstancesOf(UnsafelyCopedCollectionFieldWithAllowedGenericType.class, areNotImmutable());
}
@Test
public void onlyOneReasonIsRaisedForAssigningAbstractTypeToField() throws Exception {
AnalysisResult analysisResult = getAnalysisResult(MutableByAssigningAbstractTypeToField.class);
Collection<MutableReasonDetail> reasons = analysisResult.reasons;
assertThat(formatReasons(reasons), reasons.size(), is(1));
Reason reason = reasons.iterator().next().reason();
assertThat(reason, CoreMatchers.<Reason> is(ABSTRACT_TYPE_TO_FIELD));
}
}